package com.luo.demo.security.config;

import org.springframework.core.log.LogMessage;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.function.Function;

/**
 * Generates a default log out page.
 *
 * @author Rob Winch
 * @since 5.1
 */
public class FrontChannelLogoutGeneratingFilter extends OncePerRequestFilter {

	private RequestMatcher matcher = new AntPathRequestMatcher("/front_logout", "GET");

	public FrontChannelLogoutGeneratingFilter(String front_channel_url) {
		if (null != front_channel_url) {
			this.matcher = new AntPathRequestMatcher(front_channel_url, "GET");
		}
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		if (this.matcher.matches(request)) {
			renderLogout(request, response);
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace(LogMessage.format("Did not handle front-channel logout since request did not match [%s]",
						this.matcher));
			}
			filterChain.doFilter(request, response);
		}
	}

	private void renderLogout(HttpServletRequest request, HttpServletResponse response) throws IOException {
		logger.info("front logout");
		//clear session
		HttpSession session = request.getSession(false);
		if (session != null) {
			session.invalidate();
			if (this.logger.isDebugEnabled()) {
				this.logger.debug(LogMessage.format("Invalidated session %s", session.getId()));
			}
		}

		//clear SecurityContext
		SecurityContext context = SecurityContextHolder.getContext();
		if (null != context) {
			SecurityContextHolder.clearContext();
			context.setAuthentication(null);
		}

		//resp 200
		response.setStatus(HttpStatus.OK.value());
		response.getWriter().flush();

	}

}